package com.ecoolex.ying.space.core.manager;

import com.alibaba.fastjson.JSON;
import com.ecoolex.framework.common.annotation.Description;
import com.ecoolex.framework.common.enums.ResultCode;
import com.ecoolex.framework.common.util.BizAssert;
import com.ecoolex.framework.common.util.Check;
import com.ecoolex.framework.common.util.CollectorUtil;
import com.ecoolex.ying.space.core.dao.GoodsProductDAO;
import com.ecoolex.ying.space.entity.Goods;
import com.ecoolex.ying.space.entity.GoodsProduct;
import com.ecoolex.ying.space.entity.GoodsProduct.Column;
import com.ecoolex.ying.space.entity.GoodsProductExample;
import com.ecoolex.ying.space.enums.GoodsProductStatus;
import com.ecoolex.ying.space.pojo.EditGoodsProductDTO;
import com.ecoolex.ying.space.pojo.EditSpecDTO;
import com.ecoolex.ying.space.pojo.EditSpecGroupDTO;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.util.*;

@Service
public class GoodsProductManager {
    @Autowired
    private GoodsProductDAO dao;

    @Autowired
    private GoodsManager goodsManager;
    @Autowired
    private PickGoodsProductManager pickGoodsProductManager;

    void refresh(Goods goods, List<EditSpecGroupDTO> specGroup, String updateUser) {
        // 迭代出所有可能
        Set<List<EditSpecDTO>> result = Sets.newLinkedHashSet();
        forEachAllResult(result, specGroup, 0, Lists.newArrayList());

        BizAssert.isTrue(result.size() <= 1000, "规格组合必须小于等于1000种组合");

        // 旧的产品
        List<GoodsProduct> oldList = queryByGoodsId(goods.getGoodsId());

        Iterator<List<EditSpecDTO>> iterator = result.iterator();
        for (int i = 0; iterator.hasNext(); i++) {
            List<EditSpecDTO> specList = iterator.next();

            // 根据规格排序
            String specIds = Arrays.toString(
                    specList.stream().map(EditSpecDTO::getSpecId).sorted(Integer::compareTo).toArray(Integer[]::new));
            String specNames = Arrays.toString(specList.stream().map(EditSpecDTO::getName).toArray(String[]::new));

            GoodsProduct product = oldList.stream().collect(CollectorUtil.first(p -> p.getSpecIds().equals(specIds)));

            if (Check.notNull(product)) {
                product.setSpecNames(specNames);
                product.setSpecSorting(i + 1);
                refresh(product, updateUser);

                // 移除已经存在的
                oldList.remove(product);
            } else {
                product = new GoodsProduct();
                product.setGoodsId(goods.getGoodsId());
                product.setSpecIds(specIds);
                product.setSpecNames(specNames);
                product.setSpecSorting(i + 1);
                create(product, updateUser);
            }
        }

        // 删除多余的
        oldList.forEach(old -> delete(old, updateUser));

    }

    private void forEachAllResult(final Set<List<EditSpecDTO>> result, List<EditSpecGroupDTO> specGroup, int index, List<EditSpecDTO> specList) {
        EditSpecGroupDTO group = specGroup.get(index);

        boolean flag = index < specGroup.size() - 1;
        group.getSpecList().forEach(spec -> {
            List<EditSpecDTO> newSpecList = Lists.newArrayList(specList);
            newSpecList.add(spec);
            if (flag) {
                forEachAllResult(result, specGroup, (index + 1), newSpecList);
            } else {
                result.add(newSpecList);
            }
        });
    }

    private void create(GoodsProduct product, String createUser) {
        product.setStockNumber(0);
        product.setUsedStockNumber(0);
        product.setSoldNumber(0);
        product.setStatus(GoodsProductStatus.NORMAL.real());
        product.setDeleted(GoodsProduct.NOT_DELETED);
        product.setCreateUser(createUser);
        product.setCreateTime(Date.from(Instant.now()));
        product.setUpdateUser(createUser);
        product.setUpdateTime(Date.from(Instant.now()));

        dao.insert(product);
    }

    private void refresh(GoodsProduct product, String updateUser) {
        product.setUpdateUser(updateUser);
        product.setUpdateTime(Date.from(Instant.now()));
        dao.updateByPrimaryKeySelective(product,
                Column.specNames,
                Column.specSorting,
                Column.updateUser,
                Column.updateTime);

        // 修改关联的数据
        pickGoodsProductManager.refresh(product, updateUser);
    }

    private void delete(GoodsProduct product, String updateUser) {
        long countPickProductUsedNumber = pickGoodsProductManager.countByProductId(product.getProductId());
        BizAssert.isTrue(countPickProductUsedNumber == 0, "存在{}个优选产品正在使用该产品", countPickProductUsedNumber);

        product.setDeleted(GoodsProduct.IS_DELETED);
        product.setUpdateUser(updateUser);
        product.setUpdateTime(Date.from(Instant.now()));

        dao.updateByPrimaryKeySelective(product, Column.deleted, Column.updateUser, Column.updateTime);
    }

    void deleteByGoodsId(Integer goodsId, String updateUser) {
        GoodsProduct product = new GoodsProduct();
        product.setDeleted(GoodsProduct.IS_DELETED);
        product.setUpdateUser(updateUser);
        product.setUpdateTime(Date.from(Instant.now()));

        GoodsProductExample example = new GoodsProductExample();
        example.createCriteria().andGoodsIdEqualTo(goodsId).andDeletedEqualTo(GoodsProduct.NOT_DELETED);

        dao.updateByExampleSelective(product, example, Column.deleted, Column.updateUser, Column.updateTime);
    }

    @Transactional
    public void update(EditGoodsProductDTO edit, String updateUser) {
        GoodsProduct record = new GoodsProduct();
        record.setName(edit.getName());
        record.setImage(edit.getImage());
        record.setCoded(edit.getCoded());
        record.setCounterPrice(edit.getCounterPrice());
        record.setRetailPrice(edit.getRetailPrice());
        record.setWeight(edit.getWeight());
        record.setBarCodes(Check.isNull(edit.getBarCodes()) ? null : JSON.toJSONString(edit.getBarCodes()));
        record.setParameters(Check.isNull(edit.getParameters()) ? null : JSON.toJSONString(edit.getParameters()));
        record.setUpdateUser(updateUser);
        record.setUpdateTime(Date.from(Instant.now()));

        GoodsProductExample example = new GoodsProductExample();
        example.createCriteria().andProductIdEqualTo(edit.getProductId()).andDeletedEqualTo(GoodsProduct.NOT_DELETED);

        int row = dao.updateByExampleSelective(record,
                example,
                Column.name,
                Column.image,
                Column.coded,
                Column.barCodes,
                Column.counterPrice,
                Column.retailPrice,
                Column.weight,
                Column.parameters,
                Column.updateUser,
                Column.updateTime);

        BizAssert.isTrue(row == 1, ResultCode.BIZ.build(1), "更新失败, 可能产品不存在");

        // 刷新价格
        goodsManager.refreshProductPrice(edit.getProductId());
        // TODO BarCode没存入
    }

    GoodsProduct getByGoodsIdAndProductId(Integer goodsId, Integer productId) {
        GoodsProductExample example = new GoodsProductExample();
        example.createCriteria().andGoodsIdEqualTo(goodsId).andProductIdEqualTo(productId).andDeletedEqualTo(GoodsProduct.NOT_DELETED);
        return dao.selectOneByExample(example);
    }

    public GoodsProduct getById(Integer productId) {
        return dao.selectByPrimaryKeyWithLogicalDelete(productId, GoodsProduct.NOT_DELETED);
    }

    public List<GoodsProduct> queryByGoodsId(Integer goodsId) {
        GoodsProductExample example = new GoodsProductExample();
        example.createCriteria().andGoodsIdEqualTo(goodsId).andDeletedEqualTo(GoodsProduct.NOT_DELETED);
        example.orderBy(Column.specSorting.asc());
        return dao.selectByExample(example);
    }
}